Android Instrumentation Test的使用

Android Instrumentation Test的使用

Instrumentation Test一直都存在,但是一直被忽略,大部分的代码都不会有UT的编写,所以更加不会有IT的编写了。简单来说I(nstrumentation)T(est)是需要跑到具体手机上的测试用例,对于我们需要用到GPU,DSP的应用来说还是非常实用的,毕竟离线环境和线上环境千差万别,最终还是要以具体的板子效果为准。

初始化配置

配置的部分是第一个坑,整个测试到入口跟MainActivity很像,需要先设定一个testInstrumentationRunner,这个部分是配置在build.gradle中的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
android {
......
defaultConfig {
minSdkVersion androidSdk.minVersion
targetSdkVersion androidSdk.targetVersion
versionCode rootProject.ext.verCode
versionName rootProject.ext.verName
testInstrumentationRunner "com.example.test.SelfTestRunner"
}
......
}
dependencies {
......
//test
androidTestImplementation 'androidx.annotation:annotation:1.1.0'
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test:rules:1.1.0'
}

代码编写

目录结构上,Instrumentation Test是分属在androidTest目录下,跟main的部分同级,这部分跟普通android project类似,需要创建对应的代码包名,类名即可,不同的是,通过挂靠在对应android module下的Instrumentation Test,其中的androidTest代码是可以直接引用到当前模块下的任何包的,包括了implemetation aars/jars,同时也可以基于Android SDK进行代码编写,所以这一切是极大的方便了做测试,也是实现了测试/真实代码的解耦。

注解类

在编写代码的过程中,主要有4类注解需要注意,分别是:

1
2
3
4
import org.junit.runner.RunWith;
import org.junit.Before;
import org.junit.Test;
import org.junit.After;

其中:
RunWith是声明了当前TestRunner中的测试对象
Before,Test,After则可以理解成“测试对象在整个测试过程中生命周期的hook函数”,分别对应了“测试前”,“测试时”,以及“测试后”。
部分会用到一些特殊权限的,比如读写sdcard,还需要使用到:

1
import org.junit.Rule;

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.demo.test;
@RunWith(AndroidJUnit4.class)
public class JustDemoTest {
@Rule
public GrantPermissionRule mReadRule = GrantPermissionRule.grant(Manifest.permission.READ_EXTERNAL_STORAGE);
@Before
public void beforeTesting() {
......
}
@Test
public void classifierTest() {
......
}
@After
public void afterTesting() {
......
}
}

Runner主体

根据之前在build.gradle中的声明:testInstrumentationRunner "com.example.test.SelfTestRunner",我们需要在代码中创建对应的Runner:

1
2
public class SelfTestRunner extends AndroidJUnitRunner {
}

根据继承关系,我们可以看出:

  • com.example.test.SelfTestRunner
    • androidx.test.runner.AndroidJUnitRunner
      • androidx.test.runner.MonitoringInstrumentation
        • androidx.test.internal.runner.hidden.ExposedInstrumentationApi
          • android.app.Instrumentation

因此Runner其实本质上是Instrumentation,而它几句话概括一下:

Android instrumentation is a set of control methods or hooks in the Android system.
These hooks control an Android component independently of its normal lifecycle.
They also control how Android loads applications.

所以整个Instrumentation的权限/能力是很强的,在实作中,我更多的是作为整个Test的入口,用来做一些参数解析,或者是初始化的工作(通过Bundle)。

1
2
3
4
5
6
7
8
9
10
public class I19tTestRunner extends AndroidJUnitRunner {
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
......
mModelName = bundle.getString("model");
mInterval = bundle.getInt("interval", 500);
......
}
}

编译及运行

编译

assemble AndroidTest

android gradle中目前已经有现成的task环境,通常我们可以使用:gradlew.bat assembleDebugAndroidTest或者是gradlew.bat assembleReleaseAndroidTest,当编译完成以后,我们可以在module的build/outputs/apk/androidTest/debug或者是release目录看到生成的apk文件。

安装

adb install apk

一般而言,我们都是通过adb命令来安装该Instrumentation Test apk

运行

Runtime的时候,我们需要先通过adb shell pm list instrumentation,查询当前手机中支持的instrumentation,通常安装对应的instrumentation apk之后,会出现如下的显示:

adb shell pm list instrumentation
instrumentation:com.example.test/.SelfTestRunner (target=com.example.app)

然后可以使用adb shell am instrument命令运行,这条命令的关键参数如下:

1
2
3
4
5
6
7
8
9
10
instrument [-r] [-e <NAME> <VALUE>] [-w]<COMPONENT>
Start an Instrumentation. Typically this target <COMPONENT> is in the
form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there
is only one instrumentation. Options are:
-r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with
[-e perf true] to generate raw output for performance measurements.
-e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a
common form is [-e <testrunner_flag> <value>[,<value>...]].
-w: wait for instrumentation to finish before returning. Required for
test runners.

结合我们声明的Runner:com.example.test/.SelfTestRunner以及编写的tester:JustDemoTest,测试命令如下:

1
adb shell am instrument -r -w -e class "com.demo.test.JustDemoTest" -e model demo -e interval 800 com.example.test/.SelfTestRunner